package com.hitqz.robot.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hitqz.robot.api.business.enums.*;
import com.hitqz.robot.api.business.event.FormUpdateEvent;
import com.hitqz.robot.api.business.model.vo.form.FormConfigModalVo;
import com.hitqz.robot.api.business.model.vo.form.FormFieldConfigModalVo;
import com.hitqz.robot.api.business.model.vo.patrol.PatrolItemOptionVo;
import com.hitqz.robot.api.common.dto.form.FormConfigDto;
import com.hitqz.robot.api.common.dto.form.FormFieldConfigDto;
import com.hitqz.robot.api.common.dto.form.FormFieldConfigUpdateDto;
import com.hitqz.robot.api.common.entity.*;
import com.hitqz.robot.biz.mapper.FormConfigMapper;
import com.hitqz.robot.biz.service.*;
import com.hitqz.robot.driver.parent.RobotDriverService;
import com.hitqz.robot.netty.service.Send2ServerService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wengyx
 * @date 2024/8/7
 */
@Service
@AllArgsConstructor
@Slf4j
public class FormConfigIml extends ServiceImpl<FormConfigMapper, FormConfig> implements FormConfigService {

    private final FormFieldConfigService formFieldConfigService;

    private final RobotDriverService robotDriverService;

    private final RobotService robotService;

    private final RobotMapPosService robotMapPosService;

    private final PatrolItemService patrolItemService;

    private Send2ServerService send2ServerService;

    private final RobotEquipmentService robotEquipmentService;


    @Override
    public FormConfigModalVo getFormModal(String formName) {
        FormConfig formConfig = this.getOne(Wrappers.<FormConfig>lambdaQuery().eq(FormConfig::getFormName, formName).last("limit 1"));
        if (formConfig == null){
            return null;
        }
        List<FormFieldConfig> list = formFieldConfigService.list(Wrappers.<FormFieldConfig>lambdaQuery().in(FormFieldConfig::getFormId, formConfig.getId()));
        FormConfigModalVo modalVo = new FormConfigModalVo();
        modalVo.setFormTitle(formConfig.getFormTitle());
        modalVo.setFormName(formConfig.getFormName());
        List<FormFieldConfigModalVo> fieldResponses = list.stream().map(field -> {
            FormFieldConfigModalVo fieldVo = new FormFieldConfigModalVo();
            fieldVo.setId(field.getId());
            fieldVo.setName(field.getFieldName());
            fieldVo.setLabel(field.getFieldLabel());
            fieldVo.setType(field.getFieldType());
            fieldVo.setDefaultValue(field.getDefaultValue());
            fieldVo.setCurrentValue(field.getCurrentValue());
            fieldVo.setRequired(field.getRequired());
            fieldVo.setMin(field.getMinValue());
            fieldVo.setMax(field.getMaxValue());
            fieldVo.setPattern(field.getPattern());
            // 处理 options
            if ("radio".equals(field.getFieldType())
                    || "select".equals(field.getFieldType())
                    || "checkbox".equals(field.getFieldType())
                    || "transfer".equals(field.getFieldType())
                    || "select-multiple".equals(field.getFieldType())
            ) {
                if (StrUtil.isNotBlank(field.getOptions())) {
                    fieldVo.setOptions(JSONUtil.toList(field.getOptions(), String.class));
                } else {
                    //这里处理下动态内容
                    this.setDynamicOptions(fieldVo);
                }
            }
            return fieldVo;
        }).collect(Collectors.toList());
        modalVo.setFields(fieldResponses);
        return modalVo;
    }

    @Override
    public String submitFormModal(FormConfigModalVo dto) {
        List<FormFieldConfigModalVo> fields = dto.getFields();
        List<Integer> fieldIdLists = fields.stream().map(FormFieldConfigModalVo::getId).toList();
        if (!fieldIdLists.isEmpty()){
            List<FormFieldConfig> oldFieldConfigs = formFieldConfigService.list(Wrappers.<FormFieldConfig>lambdaQuery().in(FormFieldConfig::getId, fieldIdLists));
            Map<Integer, List<FormFieldConfig>> oldFieldIdMap = oldFieldConfigs.stream().collect(Collectors.groupingBy(FormFieldConfig::getId));
            List<FormFieldConfigUpdateDto> updateFields = new ArrayList<>();
            List<FormFieldConfig> newFieldConfigs = new ArrayList<>();
            for (FormFieldConfigModalVo field : fields) {
                FormFieldConfig oldFieldConfig = oldFieldIdMap.get(field.getId()).get(0);
                if (oldFieldConfig==null){
                    continue;
                }
                if (!oldFieldConfig.getCurrentValue().equals(field.getCurrentValue())) {
                    //需要更新的数据库list
                    FormFieldConfig newFieldConfig = BeanUtil.copyProperties(oldFieldConfig, FormFieldConfig.class);
                    newFieldConfig.setCurrentValue(field.getCurrentValue());
                    newFieldConfigs.add(newFieldConfig);
                    //需要更新的下发的数据
                    updateFields.add(new FormFieldConfigUpdateDto(field.getName(), oldFieldConfig.getCurrentValue(), field.getCurrentValue()));
                }
            }
            if (!newFieldConfigs.isEmpty()) {
                //更新数据库
                formFieldConfigService.updateBatchById(newFieldConfigs);
                //发布事件
                SpringUtil.getApplicationContext().publishEvent(new FormUpdateEvent(dto.getFormName(), updateFields));
            }
        }

        return "";
    }

    @Override
    public void createDefaultFormFieldConfig(FormConfigEnum formConfigEnum) {
        //创建表单
        FormConfig formConfig = new FormConfig();
        formConfig.setFormName(formConfigEnum.getFormName());
        formConfig.setFormTitle(formConfigEnum.getFormTitle());
        formConfig.setFormDescription(formConfigEnum.getFormDescription());
        this.save(formConfig);
        log.info("创建[{}-{}]表单", formConfig.getFormName(), formConfig.getFormTitle());
        //创建底下的表单字段
        List<FormFieldConfig> fieldConfigList = new ArrayList<>();
        //机器人参数表
        if (Objects.equals(RobotParamsFormFieldEnum.values()[0].getFormName(), formConfigEnum.getFormName())){
            FormConfigDto robotConfig = robotDriverService.getRobotConfig(formConfigEnum.getFormName());
            List<FormFieldConfigDto> fields = robotConfig.getFields();
            for (FormFieldConfigDto field : fields) {
                FormFieldConfig formFieldConfig = BeanUtil.copyProperties(field, FormFieldConfig.class);
                formFieldConfig.setFormId(formConfig.getId());
                fieldConfigList.add(formFieldConfig);
            }
        }
        //工单动态配置表
        for (TicketsFormFieldEnum value : TicketsFormFieldEnum.values()){
            if (Objects.equals(value.getFormName(), formConfigEnum.getFormName())){
                FormFieldConfigDto configDto = value.toConfigDto();
                FormFieldConfig formFieldConfig = BeanUtil.copyProperties(configDto, FormFieldConfig.class);
                formFieldConfig.setFormId(formConfig.getId());
                fieldConfigList.add(formFieldConfig);
            }
        }
        if (!fieldConfigList.isEmpty()) {
            log.info("创建[{}-{}]表单下的字段", formConfig.getFormName(), formConfig.getFormTitle());
            formFieldConfigService.saveBatch(fieldConfigList);
        }
    }

    @Override
    public void syncFormMoal(String formName) {
        FormConfigModalVo vo = this.getFormModal(formName);
        Robot robot = robotService.getDefaultRobot();
        send2ServerService.syncTasks(robot, vo);
    }


    private void setDynamicOptions(FormFieldConfigModalVo vo){
        String name = vo.getName();
        List<String> optionList = new ArrayList<>();
        if (Objects.equals(name,TicketsFormFieldEnum.PATROL_END_POS_ID.getFieldName())){
            Robot robot = robotService.getDefaultRobot();
            List<RobotMapPos> posList = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(StrUtil.isNotBlank(robot.getMapCode()), RobotMapPos::getMapCode, robot.getMapCode()));

            for (RobotMapPos pos : CollUtil.emptyIfNull(posList)) {
                Map<String,String> option=new HashMap<>();
                option.put("value",pos.getId().toString());
                option.put("label",pos.getName());
                optionList.add(JSON.toJSONString(option));
            }
            vo.setDefaultValue("");
        }
        if (Objects.equals(name,TicketsFormFieldEnum.TARGET_POS_CODE.getFieldName()) || Objects.equals(name,TicketsFormFieldEnum.SOURCE_POS_CODE.getFieldName())){
            Robot robot = robotService.getDefaultRobot();
            List<RobotMapPos> posList = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(StrUtil.isNotBlank(robot.getMapCode()), RobotMapPos::getMapCode, robot.getMapCode()));
            for (RobotMapPos pos : CollUtil.emptyIfNull(posList)) {
                Map<String,String> option=new HashMap<>();
                option.put("value",pos.getCode());
                option.put("label",pos.getName());
                optionList.add(JSON.toJSONString(option));
            }
        }
        if (Objects.equals(name,TicketsFormFieldEnum.PATROL_ITEM_IDS.getFieldName())){
            List<PatrolItemOptionVo> list = patrolItemService.getOptionVoList();
            for (PatrolItemOptionVo itemOptionVo : CollUtil.emptyIfNull(list)) {
                if (StrUtil.isBlank(itemOptionVo.getPosCode())){
                    continue;
                }
                Map<String,String> option=new HashMap<>();
                option.put("value",itemOptionVo.getId().toString());
                String label ="[点"+itemOptionVo.getPosCode() +"]["+itemOptionVo.getDevName()+"] "+itemOptionVo.getName()+" ("+itemOptionVo.getObjectName()+")";
                option.put("label",label);
                optionList.add(JSON.toJSONString(option));
            }
        }
        if (name.contains(TicketsFormFieldEnum.EQUIPMENT_LIST.getFieldName())) {
            String brand = name.split("-")[1];
            List<RobotEquipment> robotEquipments = robotEquipmentService.list(Wrappers.<RobotEquipment>lambdaQuery()
                    //.eq(RobotEquipment::getType, EquipmentEnum.PLC.getType())
                    .eq(RobotEquipment::getBrand, brand));
            for (RobotEquipment itemOptionVo : CollUtil.emptyIfNull(robotEquipments)) {
                Map<String,String> option=new HashMap<>();
                option.put("value", String.valueOf(itemOptionVo.getId()));
                option.put("label",itemOptionVo.getName());
                optionList.add(JSON.toJSONString(option));
            }
        }
        if (!optionList.isEmpty()) {
            vo.setOptions(optionList);
        }
    }


}
